home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / modelers / geomview / source.lha / Geomview / src / lib / geometry / cmodel / cmodel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-01  |  15.4 KB  |  611 lines

  1. /* conformal model graphics for geomview */
  2.  
  3. #include <stdlib.h>
  4. #include "cmodelP.h"
  5. #include "mgP.h"
  6.  
  7. #ifndef alloca
  8. #include <alloca.h>
  9. #endif
  10.  
  11. static int cm_show_subdivision = 0;
  12. static int cm_maxrefine = 6;
  13. static double cm_cosmaxbend = .95;
  14.  
  15. static int alldone = TRUE;
  16. static int curv;
  17.  
  18. struct vertex *edge_start(struct edge *e, int ori);
  19. void split_triangle(struct triangle *t);
  20. void split_edge(struct edge *e, splitfunc split);
  21. void refine_once(splitfunc split);
  22. void refine();
  23. struct edge *new_edge_p(struct vertex *v1, struct vertex *v2);
  24. void make_new_quad(Transform T, HPoint3 *p, ColorA *c);
  25. void make_new_triangle(HPoint3 *a, HPoint3 *b, HPoint3 *c, ColorA *col,
  26.                Transform T, Poly *p, int allvisible);
  27.  
  28. void set_cm_refine(double cm_cmb, int cm_mr, int cm_ss)
  29. {
  30.   /* These tests allow us to call this routine in a way that sets
  31.      only some of the values; parameters with out-of-range values
  32.      are not set. */
  33.  
  34.   if (cm_cmb >= 1 && cm_cmb <=1)
  35.     cm_cosmaxbend = cm_cmb;
  36.   if (cm_mr >=0)
  37.     cm_maxrefine = cm_mr;
  38.   if (cm_mr >=0)
  39.     cm_show_subdivision = cm_ss;
  40.   return;
  41. }
  42.  
  43. void cmodel_clear(int space)
  44. {
  45.    static int initialized = FALSE; 
  46.    
  47.    if (initialized) {
  48.       clear_all_vertexs();
  49.       clear_all_edges();
  50.       clear_all_triangles();
  51.       }
  52.    else {
  53.       initialize_vertexs();
  54.       initialize_edges();
  55.       initialize_triangles();
  56.       initialized = TRUE;
  57.       }
  58.    if (space & TM_SPHERICAL)
  59.       curv = 1;
  60.    else if (space & TM_HYPERBOLIC)
  61.       curv = -1;
  62.    else if (space & TM_EUCLIDEAN)
  63.       curv = 0;
  64.    /* else error */
  65.    }
  66.  
  67. void cm_read_quad(Quad *q)
  68. {
  69.    int i = q->maxquad;
  70.    QuadP *qp = q->p;
  71.    QuadC *qc = q->c;
  72.    Transform T;
  73.  
  74.    mggettransform(T);
  75.    
  76.    if (q->flag & VERT_C) {
  77.       while (i-- > 0)
  78.          make_new_quad(T, (HPoint3 *)qp++, (ColorA *)qc++);
  79.       } 
  80.    else {
  81.       while (i-- > 0)
  82.          make_new_quad(T, (HPoint3 *)qp++, NULL);
  83.       }
  84.    return;
  85.    }
  86.  
  87. void make_new_quad(Transform T, HPoint3 *p, ColorA *c)
  88. {
  89.    HPoint3 tp, polar;
  90.    int i;
  91.    struct vertex *v[4], *vx;
  92.    struct edge *e1, *e2, *e3, *e4, *e5;
  93.    int apflags = _mgc->astk->ap.flag;
  94.  
  95.    if((apflags & (APF_EDGEDRAW | APF_FACEDRAW | APF_NORMALDRAW)) == 0)
  96.     return;
  97.  
  98.    /* make 4 new vertices */
  99.    tp.w = 1.;
  100.    if (c) { /* vertex colors defined */
  101.       for (i = 0; i < 4; i++) {
  102.          projective_to_conformal(curv, p++, T, (Point3 *)&tp);
  103.          v[i] = simple_new_vertex(&tp, c++);
  104.          }
  105.       }
  106.    else {  /* no vertex colors so get color from appearance stack */
  107.       c = (ColorA*)&_mgc->astk->ap.mat->diffuse;
  108.       for (i = 0; i < 4; i++) {
  109.          projective_to_conformal(curv, p++, T, (Point3 *)&tp);
  110.          v[i] = simple_new_vertex(&tp, c);
  111.          }
  112.       }
  113.    triangle_polar_point(curv, (Point3 *)&v[0]->V.pt, (Point3 *)&v[1]->V.pt,
  114.                         (Point3 *)&v[2]->V.pt, &polar);
  115.    for (i=0; i<4; i++)
  116.       v[i]->polar = polar;
  117.  
  118.    e1 = new_edge_p(v[0], v[1]); 
  119.    e2 = new_edge_p(v[1], v[2]); 
  120.    e4 = new_edge_p(v[2], v[3]); 
  121.    e5 = new_edge_p(v[3], v[0]);
  122.  
  123.    if(apflags & (APF_FACEDRAW|APF_NORMALDRAW)) {
  124.        /* make two triangles and five edges */
  125.        new_triangle(e1, e2,
  126.         e3 = new_edge_p(v[2], v[0]),
  127.         TRUE, TRUE, TRUE, NULL);
  128.        new_triangle(e3, e4, e5,
  129.         FALSE, TRUE, TRUE, NULL);
  130.        }
  131.  
  132.    /* set the four original edges visible if required */
  133.    if (apflags & APF_EDGEDRAW) {
  134.       e1->visible = TRUE;
  135.       e2->visible = TRUE; 
  136.       e4->visible = TRUE; 
  137.       e5->visible = TRUE; 
  138.       }
  139.    return;
  140.    }
  141.  
  142. void cm_draw_mesh(Mesh *m)
  143. {
  144.    HPoint3 *pt, *newpt, *ppt;
  145.    Point3 *n, *newn, *pn;
  146.    ColorA *c, *newc = NULL, *pc;
  147.    mgshadefunc shader = _mgc->astk->shader;
  148.    int i, npt;
  149.    Transform T;
  150.  
  151.    mggettransform(T);
  152.    
  153.    mgpushtransform();
  154.    mgidentity();
  155.  
  156.    npt = m->nu * m->nv;
  157.    pt = m->p;
  158.    n = m->n;
  159.    newpt = ppt = (HPoint3 *)alloca(npt * sizeof(HPoint3));
  160.    newn = pn = (Point3 *)alloca(npt * sizeof(Point3));
  161.    if(_mgc->astk->useshader) {
  162.     newc = pc = (ColorA *)alloca(npt * sizeof(ColorA));
  163.     c = m->c ? m->c : (ColorA *)&_mgc->astk->mat.diffuse;
  164.    }
  165.    for (i = 0; i < npt; ++i) {
  166.       projective_vector_to_conformal(curv, pt, n, T, (Point3 *)ppt, pn);
  167.       ppt->w = 1.;
  168.       if(newc) {
  169.     (*shader)(1, ppt, pn, c, pc);
  170.     pc++;
  171.     if(m->c) c++;
  172.       }
  173.       ++pt; ++n; ++ppt; ++pn;
  174.       }
  175.    mgmesh(m->flag, m->nu, m->nv, newpt, newn, newc ? newc : m->c);
  176.    mgpoptransform();
  177.    }
  178.  
  179. void cm_read_vect(Vect *v)
  180. {
  181.    int i, nv, nc;
  182.    HPoint3 pt, *p = v->p;
  183.    ColorA *c = v->c, *col = (ColorA *)&_mgc->astk->mat.edgecolor;
  184.    struct vertex *v0, *v1, *v2;
  185.    struct edge *e;
  186.    Transform T;
  187.  
  188.    mggettransform(T);
  189.  
  190.    pt.w = 1.;
  191.    for (i = 0; i < v->nvec; i++) {
  192.       nv = abs(v->vnvert[i]);
  193.       nc = v->vncolor[i];
  194.  
  195.       /* get position, color and make a new vertex */
  196.       projective_to_conformal(curv, p++, T, (Point3 *)&pt);
  197.       if (nc > 0) {nc--; col = c++;}
  198.       v0 = v1 = simple_new_vertex(&pt, col);
  199.  
  200.       if (nv == 1) { /* point, not polyline */
  201.          v0->visible = TRUE;
  202.      continue;
  203.      }
  204.  
  205.       while (--nv > 0) { /* copy polyline */
  206.  
  207.          /* get position, color and make a new vertex */
  208.          projective_to_conformal(curv, p++, T, (Point3 *)&pt);
  209.          if (nc > 0) {nc--; col = c++;}
  210.      v2 = simple_new_vertex(&pt, col);
  211.  
  212.      e = new_edge_p(v1, v2);
  213.      e->visible = e->hascolor = TRUE;
  214.      v1 = v2;
  215.      }
  216.  
  217.       if (v->vnvert[i] < 0) { /* if polyline is closed */
  218.      e = new_edge_p(v2, v0);
  219.      e->visible = e->hascolor = TRUE;
  220.      }
  221.       }
  222.    }
  223.  
  224. void cm_read_polylist(PolyList *polylist)
  225. {
  226.    int i, j, nv, n, vertcolors, facecolors;
  227.    HPoint3 center;
  228.    ColorA *col;
  229.    Transform T;
  230.    Poly *p;
  231.  
  232.    mggettransform(T);
  233.  
  234.    p = polylist->p;
  235.    n = polylist->n_polys;
  236.    vertcolors = (polylist->flags & (PL_HASVCOL|PL_HASPCOL)) == PL_HASVCOL;
  237.    facecolors = (polylist->flags & PL_HASPCOL);
  238.    col = (ColorA*)&_mgc->astk->mat.diffuse;
  239.    for (i = 0; i < n; i++) {
  240.       if(facecolors) col = &p->pcol;
  241.       nv = p->n_vertices;
  242.       if (nv == 3) {
  243.      make_new_triangle(&p->v[0]->pt,
  244.                &p->v[1]->pt,
  245.                &p->v[2]->pt,
  246.                col, T, p, TRUE);
  247.          }
  248.       else {
  249.      center.x = center.y = center.z = center.w = 0;
  250.      for (j = 0; j < nv; j++)
  251.         HPt3Add(¢er, &p->v[j]->pt, ¢er);
  252.      for (j = 1; j < nv; j++)
  253.              make_new_triangle(&p->v[j-1]->pt, &p->v[j]->pt, ¢er,
  254.                   vertcolors ? &p->v[j]->vcol : col, T, p, FALSE);
  255.      make_new_triangle(&p->v[nv-1]->pt, &p->v[0]->pt, ¢er,
  256.                 vertcolors ? &p->v[0]->vcol : col, T, p, FALSE);
  257.          }
  258.       ++p;
  259.       }
  260.    }
  261.  
  262. void make_new_triangle(HPoint3 *a, HPoint3 *b, HPoint3 *c, ColorA *col,
  263.                Transform T, Poly *p, int allvisible)
  264. {
  265.    struct vertex v, *v1, *v2, *v3;
  266.    Point3 ap, bp, cp;
  267.    struct edge *e1, *e2, *e3;
  268.    int apflags = _mgc->astk->ap.flag;
  269.  
  270.    projective_to_conformal(curv, a, T, &ap);
  271.    projective_to_conformal(curv, b, T, &bp);
  272.    projective_to_conformal(curv, c, T, &cp);
  273.  
  274.  /*fprintf(stderr,"Making tri %.1f %.1f %.1f, %.1f %.1f %.1f, %.1f %.1f %.1f\n",ap.x,ap.y,ap.z,bp.x,bp.y,bp.z,cp.x,cp.y,cp.z);*/
  275.    /* convert to the conformal model */
  276.    /* make a model vertex */
  277.    triangle_polar_point(curv,&ap, &bp, &cp, &v.polar);
  278.    v.V.vcol = *col;
  279.  
  280.    v1 = new_vertex(&ap, &v, NULL);
  281.    v2 = new_vertex(&bp, &v, NULL);
  282.    v3 = new_vertex(&cp, &v, NULL);
  283.    e1 = new_edge_p(v1, v2);
  284.    e2 = new_edge_p(v2, v3); 
  285.    e3 = new_edge_p(v3, v1);
  286.  
  287.    if(apflags & (APF_FACEDRAW|APF_NORMALDRAW))
  288.        new_triangle(e1, e2, e3, TRUE, TRUE, TRUE, p);
  289.  
  290.    if (apflags & APF_EDGEDRAW) {
  291.       e1->visible = TRUE;
  292.       if (allvisible) { 
  293.          e2->visible = TRUE; 
  294.          e3->visible = TRUE; 
  295.          }
  296.       }    
  297.  
  298.    return;
  299.    }
  300.  
  301. struct edge *new_edge_p(struct vertex *v1, struct vertex *v2)
  302. {
  303.     HPoint3 polar;
  304.     edge_polar_point(curv,(Point3 *)&v1->V.pt,(Point3 *)&v2->V.pt, &polar);
  305.     return new_edge(v1,v2,&polar);
  306. }
  307.  
  308. void set_normal(HPoint3 *point, HPoint3 *polar, Point3 *normal)
  309. {
  310.    Point3 t;
  311.    
  312.    if (polar == NULL) return;
  313.    Pt3Mul(polar->w, (Point3 *)point, &t);
  314.    Pt3Sub((Point3 *)polar, &t, normal);
  315.  /*fprintf(stderr,"sn gives %.2f %.2f %.2f (%.2f) for polar %.2f %.2f %.2f %.2f\n",normal->x,normal->y,normal->z,sqrt(Pt3Dot(normal,normal)),polar->x,polar->y,polar->z,polar->w);*/
  316.    Pt3Unit(normal);
  317.    }   
  318.  
  319. void cmodel_draw(int plflags)
  320. {
  321.    struct triangle *tp;
  322.    struct edge *ep;
  323.    struct vertex *vp;
  324.    ColorA col[2];
  325.    HPoint3 pts[2];
  326.    Vertex *Vertp, *verts;
  327.    Poly *Polyp, *polys;
  328.    int npolys, keepflags, nverts, facecolors, vertcolors, useshader, shading;
  329.    mgshadefunc shader;
  330.  
  331.    refine();
  332.  
  333.    /* set the transform to the identity before displaying anything
  334.       since Poincare model data is already transformed */
  335.    mgpushtransform();
  336.    mgidentity();
  337.  
  338.    if ((npolys = triangle_count()) != 0)
  339.       polys = Polyp = (Poly *)alloca(npolys * sizeof(Poly));
  340.  
  341.    if ((nverts = vertex_count()) != 0) 
  342.       verts = Vertp = (Vertex *)alloca(nverts * sizeof(Vertex));
  343.  
  344.    shading = _mgc->astk->ap.shading;
  345.    useshader = _mgc->astk->useshader;
  346.    shader = _mgc->astk->shader;
  347.  
  348.    vp = first_vertex();
  349.    vertcolors = plflags & (PL_HASVCOL | PL_HASPCOL);
  350.    while (vp != NULL) {
  351.       Vertp->pt = vp->V.pt;
  352.       /* visible vertices must be displayed
  353.          invisible vertices are part of faces so we
  354.      must compute normals */
  355.  
  356.       if (vp->visible) {
  357.      mgpolyline(1, &Vertp->pt, 1, &vp->V.vcol, 0);
  358.       } else if(IS_SMOOTH(shading)) {
  359.         set_normal(&vp->V.pt, &vp->polar, &Vertp->vn);
  360.     if(useshader)
  361.         (*shader)(1, &Vertp->pt, &Vertp->vn, &vp->V.vcol, &Vertp->vcol);
  362.     else
  363.         Vertp->vcol = vp->V.vcol;
  364.       }
  365.  
  366.       vp->vxp = Vertp++;
  367.       vp = vp->next;
  368.       }
  369.  
  370.    ep = first_edge();
  371.    while (ep != NULL) { /* draw visible edges */
  372.       if (ep->visible) {
  373.     pts[0] = ep->v1->V.pt;
  374.     pts[1] = ep->v2->V.pt;
  375.         if (ep->hascolor) {
  376.            col[0] = ep->v1->V.vcol;
  377.            col[1] = ep->v2->V.vcol;
  378.        mgpolyline(2, pts, 2, col, 0);
  379.         } else 
  380.        mgpolyline(2, pts, 1, &_mgc->astk->ap.mat->edgecolor, 0);
  381.     }
  382.       
  383.       ep = ep->next;
  384.       }
  385.  
  386.    tp = first_triangle();
  387.    facecolors = (plflags & (PL_HASPCOL|PL_HASVCOL));
  388.    while (tp != NULL) {
  389.       tp->v[0] = edge_start(tp->e1, tp->o1)->vxp;
  390.       tp->v[1] = edge_start(tp->e2, tp->o2)->vxp;
  391.       tp->v[2] = edge_start(tp->e3, tp->o3)->vxp;
  392.       Polyp->n_vertices = 3;
  393.       Polyp->v = tp->v;
  394.       /* computation is not exact here: assume triangle is small so center
  395.       and vertex are very close together */
  396.       if(IS_SHADED(shading))
  397.     set_normal(&tp->e1->v1->V.pt, &tp->e1->v1->polar, &Polyp->pn);
  398.  
  399.       if(useshader)
  400.     (*shader)(1, &tp->v[0]->pt, &Polyp->pn, &tp->e1->v1->V.vcol, &Polyp->pcol);
  401.       else
  402.     Polyp->pcol = tp->e1->v1->V.vcol;
  403.  
  404.       Polyp++;
  405.       tp = tp->next;
  406.       }
  407.    
  408.    if (npolys) {
  409.       keepflags = _mgc->astk->ap.flag;
  410.       if (!cm_show_subdivision)
  411.       _mgc->astk->ap.flag &= ~APF_EDGEDRAW;
  412.  
  413.       plflags = (plflags &~ (PL_HASPCOL|PL_HASVCOL))
  414.             | (IS_SMOOTH(shading) ? PL_HASVCOL : PL_HASPCOL);
  415.  
  416.       mgpolylist(npolys, polys, nverts, verts, plflags);
  417.       _mgc->astk->ap.flag = keepflags;
  418.       }
  419.  
  420.    /* restore the current transform */
  421.    mgpoptransform();
  422.    return;
  423.    }
  424.  
  425. void refine()
  426. {
  427.    int maxsteps = cm_maxrefine;
  428.  
  429.  
  430.    alldone = FALSE;
  431.    
  432.    /* should do edges at infinity here first */
  433.    
  434.    while (!alldone && maxsteps-- > 0) {
  435.       alldone = TRUE;
  436.       refine_once(edge_split);
  437.       }
  438.    
  439.    return;
  440.    }
  441.  
  442. void refine_once(splitfunc split)
  443. {
  444.    struct edge *ep = first_edge(), *le = get_last_edge();
  445.    struct triangle *tp = first_triangle(), *lt = get_last_triangle();
  446.  
  447.    /* split all long edges */
  448.    while (ep != NULL) {
  449.       split_edge(ep, split);
  450.       if (ep == le) break;
  451.       ep = ep->next;
  452.       } 
  453.    
  454.    if (alldone) return;
  455.    
  456.    /* now split all triangles that have had edges split */
  457.    while (tp != NULL) {
  458.       split_triangle(tp);
  459.       if (tp == lt) break;
  460.       tp = tp->next;
  461.       }
  462.  
  463.    return;
  464.    }
  465.  
  466. /* decides whether to split an edge and if so sets the split flag,
  467.    creates a new edge and drops it into the structure */
  468.  
  469. void split_edge(struct edge *e, splitfunc split)
  470. {
  471.    struct vertex *mid;
  472.    
  473.    if (e->small) return;
  474.    mid = (*split)(e, cm_cosmaxbend);
  475.    if (mid == NULL) {
  476.       e->split = FALSE;
  477.       e->small = TRUE;
  478.       return;
  479.       }
  480.    e->split = TRUE;
  481.    e->other_half = new_edge(mid, e->v2, &e->polar);
  482.    e->other_half->visible = e->visible;
  483.    e->other_half->hascolor = e->hascolor;
  484.    e->v2 = mid;
  485.    alldone = FALSE;
  486.    
  487.    return;
  488.    }
  489.  
  490. struct vertex *edge_start(struct edge *e, int ori)
  491. {
  492.    return ori ? e->v1 : e->v2;
  493.    }
  494.  
  495. struct vertex *edge_mid(struct edge *e)
  496. {
  497.    return e->v2;
  498.    }
  499.  
  500. struct edge *first_half(struct edge *e, int ori)
  501. {
  502.    return ori ? e : e->other_half;
  503.    }
  504.  
  505. void split_triangle_at_one_edge(struct edge **e1, struct edge **e2, 
  506.    struct edge **e3, int *o1, int *o2, int *o3, Poly *orig)
  507. {
  508.    struct edge *ne; 
  509.    
  510.    ne = new_edge_p(edge_mid(*e1), edge_start(*e3, *o3));
  511.  
  512.    new_triangle(first_half(*e1, !*o1), *e2,       ne, 
  513.                            *o1,        *o2,       FALSE,  orig);
  514.    *e1 = first_half(*e1, *o1);
  515.    *e2 = ne;
  516.    *o2 = TRUE;
  517.    
  518.    return;
  519.    }
  520.  
  521. void split_triangle_at_two_edges(struct edge **e1, struct edge **e2, 
  522.    struct edge **e3, int *o1, int *o2, int *o3, Poly *orig)
  523. {
  524.    struct edge *ne1, *ne2; 
  525.    
  526.    ne1 = new_edge_p(edge_mid(*e1), edge_start(*e3, *o3));
  527.    ne2 = new_edge_p(edge_mid(*e1), edge_mid(*e2));
  528.  
  529.    new_triangle(first_half(*e1, !*o1), first_half(*e2, *o2), ne2, 
  530.                            *o1,                   *o2,       FALSE, orig);
  531.    new_triangle(first_half(*e2, !*o2), ne1,   ne2, 
  532.                            *o2,        FALSE, TRUE, orig);
  533.    *e1 = first_half(*e1, *o1);
  534.    *e2 = ne1;
  535.    *o2 = TRUE;
  536.    
  537.    return;
  538.    }
  539.  
  540. void split_triangle_at_three_edges(struct edge **e1, struct edge **e2, 
  541.    struct edge **e3, int *o1, int *o2, int *o3, Poly *orig)
  542. {
  543.    struct edge *ne1, *ne2, *ne3; 
  544.    
  545.    ne1 = new_edge_p(edge_mid(*e1), edge_mid(*e2));
  546.    ne2 = new_edge_p(edge_mid(*e2), edge_mid(*e3));
  547.    ne3 = new_edge_p(edge_mid(*e3), edge_mid(*e1));
  548.  
  549.    new_triangle(first_half(*e1, !*o1), first_half(*e2, *o2), ne1, 
  550.                            *o1,                   *o2,       FALSE, orig);
  551.    new_triangle(first_half(*e2, !*o2), first_half(*e3, *o3), ne2, 
  552.                            *o2,                   *o3,       FALSE, orig);
  553.    new_triangle(ne1, ne2, ne3, TRUE, TRUE, TRUE, orig);
  554.  
  555.    *e1 = first_half(*e1, *o1);
  556.    *e2 = ne3;
  557.    *o2 = FALSE;
  558.    *e3 = first_half(*e3, !*o3);
  559.  
  560.    return;
  561.    }
  562.  
  563.  
  564. void split_triangle(struct triangle *t)
  565. {
  566.    int magic;
  567.    Poly *orig; 
  568.  
  569.    if (t->small) return;
  570.    orig = t->orig_poly;
  571.    magic = t->e1->split + 2 * t->e2->split + 4 * t->e3->split;
  572.    
  573.    switch (magic) {
  574.    case 0:
  575.       t->small = TRUE;
  576.       break;
  577.    case 1:
  578.       split_triangle_at_one_edge(&t->e1, &t->e2, &t->e3, 
  579.          &t->o1, &t->o2, &t->o3, orig);
  580.       break;
  581.    case 2:
  582.       split_triangle_at_one_edge(&t->e2, &t->e3, &t->e1, 
  583.          &t->o2, &t->o3, &t->o1, orig);
  584.       break;
  585.    case 4:
  586.       split_triangle_at_one_edge(&t->e3, &t->e1, &t->e2, 
  587.          &t->o3, &t->o1, &t->o2, orig);
  588.       break;
  589.    case 3:
  590.       split_triangle_at_two_edges(&t->e1, &t->e2, &t->e3, 
  591.          &t->o1, &t->o2, &t->o3, orig);
  592.       break;
  593.    case 6:
  594.       split_triangle_at_two_edges(&t->e2, &t->e3, &t->e1, 
  595.          &t->o2, &t->o3, &t->o1, orig);
  596.       break;
  597.    case 5:
  598.       split_triangle_at_two_edges(&t->e3, &t->e1, &t->e2, 
  599.          &t->o3, &t->o1, &t->o2, orig);
  600.       break;
  601.    case 7:
  602.       split_triangle_at_three_edges(&t->e1, &t->e2, &t->e3, 
  603.          &t->o1, &t->o2, &t->o3, orig);
  604.       break;
  605.    default:
  606.       break;
  607.       }
  608.    
  609.    return;
  610.    }
  611.